package com.example.study.jetpack.compose

import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import kotlinx.coroutines.launch

/**
 *  created by ws
 *   on 2022/3/1
 *   describe:https://blog.csdn.net/Mr_Tony/article/details/118797357?spm=1001.2014.3001.5502
 */
class Compose的列表 {
    /*可以使用Column和Row来进行列表排序,只是如果需要
    * 显示大量的列表时候或者对列表进行复杂的操作狮虎,
    * 使用Column和Row会有严重的新能问题,这时候就需要使用
    * 延迟列表LazyColumn或者LazyRow会好一些.
    * 官方还提供了网格布局LazyVerticalGrid*/

    /*LazyColumn
    LazyColumn的使用方式要比Recycler简单一点
    示例
    LazyColumn {
    // Add a single item
    item {//添加一个
        Text(text = "First item")
    }

    // Add 5 items
    // 添加多个
    items(5) { index ->
        Text(text = "Item: $index")
    }

    // Add another single item
    item {
        Text(text = "Last item")
    }
}
但是实际上列表数量是一个数组时,示例:
    @Composable
    fun messageList(messages: List<String>) {// 值可以是 List或者Array两种方式
        LazyColumn {
//            items(messages.size) { message ->//遍历索引的方式
//                Text(text = messages[message])
//            }
//           items(items = messages){ message -> //遍历内容
//               Text(text = message)
//           }
            itemsIndexed(items = messages){ index, item -> //遍历内容和索引
                Text(text = "索引:$index -- 内容:$item")
            }
        }
    }
*/
    /*列表修饰
    如内外边距
    LazyColumn(
    contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
    ) {
        // ...
    }*/

    /*动画 暂时没有*/

    /*监听滚动位置
    可以使用Lazyliststate来处理,示例:
    @Composable
fun MessageList(messages: List<Message>) {
    // Remember our own LazyListState
    val listState = rememberLazyListState()

    // Provide it to LazyColumn
    LazyColumn(state = listState) {
        // ...
    }
}
根据是否滚动第一项来判断是否显示按钮可以使用
firstVisibleItemIndex和firstVisibleItemScrollOffset
@OptIn(ExperimentalAnimationApi::class) // AnimatedVisibility
@Composable
fun MessageList(messages: List<Message>) {
    Box {
        val listState = rememberLazyListState()

        LazyColumn(state = listState) {
            // ...
        }

        // Show the button if the first visible item is past
        // the first item. We use a remembered derived state to
        // minimize unnecessary compositions
        val showButton by remember {
            derivedStateOf {
                listState.firstVisibleItemIndex > 0
            }
        }

        AnimatedVisibility(visible = showButton) {
            ScrollToTopButton()
        }
    }
}

如果要认为人为控制滚动位置,可以使用scrollToItem()
和animateScrollToItem()来处理,不过连个函数使用哪个了协程:示例
*/
    @Composable
    fun MessageList(messages: List<String>) {
        val listState = rememberLazyListState()
        // Remember a CoroutineScope to be able to launch
        val coroutineScope = rememberCoroutineScope()

        LazyColumn(state = listState) {
            // ...
        }

        //ScrollToTopButton
        Text(text = "asdws", Modifier.clickable {
            coroutineScope.launch {
                // Animate scroll to the first item
                listState.animateScrollToItem(index = 0)
            }
        })
    }
    /*key
    * 默认情况下列表项的状态是和位置绑定的,倘若数据集发生改变,那么状态就会丢失,
    * 从而可能出现数据混乱的情况.所以需要使用key来进行状态保存
    * 示例:
    * @Composable
fun MessageList(messages: List<Message>) {
    LazyColumn {
        items(
            items = messages,
            key = { message ->
                // Return a stable + unique key for the item
                message.id
            }
        ) { message ->
            MessageRow(message)
        }
    }
}
*/

/*数据更改
* 列表创建完后数据就不会在更改,这里可以使用remember来进行数据的修改
*,添加,移除示例:
*  @Composable
    fun constrainLayout(){
            ConstraintLayout {
                // Create references for the composables to constrain
                val (button, text, list ) = createRefs()
//                val data = mutableListOf("a","b","c")
                val data = remember { mutableStateListOf<String>("a","b","c") }
//              val data = mutableStateListOf("a","b","c") 这种方式也可以，但是这样会导致每次重组有不同的状态，而remember因为缓存的原因却不会，详情可以了解Compose中的状态
                Button(
                    onClick = {
                        data.add("d")

                    },
                    // Assign reference "button" to the Button composable
                    // and constrain it to the top of the ConstraintLayout
                    modifier = Modifier.constrainAs(button) {
                        top.linkTo(parent.top, margin = 16.dp)
                    }
                ) {
                    Text("Button")
                }

                // Assign reference "text" to the Text composable
                // and constrain it to the bottom of the Button composable
                Text("Text", Modifier.constrainAs(text) {
                    top.linkTo(button.bottom, margin = 16.dp)
                })

                messageList(data,Modifier.constrainAs(list) {
                    top.linkTo(text.bottom, margin = 16.dp)
                })
            }
    }

    @Composable
    fun messageList(messages: List<String>,modifier: Modifier) {// 值可以是 List或者Array两种方式

        LazyColumn(modifier) {
//            items(messages.size) { message ->//遍历索引的方式
//                Text(text = messages[message])
//            }
//           items(items = messages){ message -> //遍历内容
//               Text(text = message)
//           }
            itemsIndexed(items = messages){ index, item -> //遍历内容和索引
                Text(text = "索引:$index -- 内容:$item")
            }
        }
    }
*/
    /*关于为什么使用 mutableStateListOf来进行修改数据，官方的原文如下:

    注意 ：在 Compose 中将可变对象（如 ArrayList<T> 或 mutableListOf()）用作状态会导致用户在您的应用中看到不正确或陈旧的数据。

    不可观察的可变对象（如 ArrayList<T> 或可变数据类）不能由 Compose 观察，因而 Compose 不能在它们发生变化时触发重组。

    我们建议您使用可观察的数据存储器（如 State<List<T>>）和不可变的 listOf()，而不是使用不可观察的可变对象。*/

}